package datatypes;

public class TLista implements ILista {
	private IElemento primero;

	/**
	 * Devuelve el primer elemento de la lista.
	 * 
	 * @return el primero de la lista.
	 */
	public IElemento getPrimero() {
		return primero;
	}

	/**
	 * Setea el primer elemento de la lista.
	 * 
	 * @param primero
	 *            .
	 */
	public void setPrimero(IElemento primero) {
		this.primero = primero;
	}

	/**
	 * Inserta el elemento que se pasa por parametro al final de la lista.
	 * 
	 * @return devuelve true si se inserto exitosamente el elemento. si devuelve
	 *         false es porque se le paso un elemento nulo.
	 * @param el
	 *            elemento a insertar.
	 */
	@Override
	public Boolean insertarAlFinal(IElemento elemento) {
		if (elemento != null) {
			if (primero != null) {
				TElemento aux = (TElemento) primero;
				while (aux.getSiguiente() != null) {
					aux = (TElemento) aux.getSiguiente();

				}
				aux.setSiguiente(elemento);
				return true;
			}
			primero = elemento;
			return true;
		}
		return false;
	}

	/**
	 * Inserta el elemento que se pasa por parametro en el principio de la
	 * lista.
	 * 
	 * @return devuelve true si se inserto exitosamente el elemento. si devuelve
	 *         false es porque se le paso un elemento nulo.
	 * @param el
	 *            elemento a insertar.
	 */
	@Override
	public Boolean insertarAlPrincipio(IElemento elemento) {
		if (elemento != null) {
			if (primero != null) {
				elemento.setSiguiente(primero);
				setPrimero(elemento);
				return true;
			} else {
				setPrimero(elemento);
				return true;
			}
		} else {
			return false;
		}
	}

	/**
	 * Busca un elemento en la lista con la etiqueta que se pasa por parametro.
	 * 
	 * @return devuelve el primer elemento que se encontro con la etiqueta que
	 *         se le pasa por parametro, si no se encuentra dicho elemento se
	 *         devuelve nulo.
	 * @param etiqueta
	 *            del elemento a buscar.
	 */

	@Override
	public IElemento buscarElemento(String label) {
		if (label != null) {
			IElemento aux = primero;
			while (aux != null) {
				if (aux.getEtiqueta().equals(label)) {
					return aux;
				} else {
					aux = aux.getSiguiente();
				}

			}
			return null;
		} else {
			return null;
		}
	}

	/**
	 * Elimina el primer elemento de la lista que tenga la etiqueta que se le
	 * pasa por parametro.
	 * 
	 * @param etiqueta
	 *            del elemento a eliminar
	 * @return devuelve true si se elimino exitosamente el elemento de la lista,
	 *         y false si no se encontro un elemento con esa etiqueta
	 * 
	 */
	@Override
	public Boolean eliminarElemento(String label) {
		if (label != null) {
			if (primero != null) {
				if (!primero.getEtiqueta().equals(label)) {
					IElemento aux = primero;
					while (aux.getSiguiente() != null) {
						if (aux.getSiguiente().getEtiqueta().equals(label)) {
							aux.setSiguiente(aux.getSiguiente().getSiguiente());
							return true;
						} else {
							aux = aux.getSiguiente();
						}

					}
				} else {
					setPrimero(null);
				}
			}
		}
		return false;
	}

	/**
	 * Imprime la etiqueta de cada elemento de la lista, si no tiene nigun
	 * elemento no imprime nada.
	 */
	@Override
	public void imprimirElementos() {
		if (!esVacia()) {
			IElemento aux = primero;
			while (aux != null) {
				System.out.println(aux.getEtiqueta());
				aux = aux.getSiguiente();
			}
		}
	}

	/**
	 * Elimina los elementos duplicados de la lista.
	 */
	@Override
	public void eliminarDuplicados() {
		IElemento aux = primero;
		while (aux != null) {
			IElemento aux2 = aux.getSiguiente();
			while (aux2 != null) {
				if (aux.getEtiqueta().equals(aux2.getEtiqueta())) {
					eliminarElemento(aux2.getEtiqueta());
				} else {
					aux2 = aux2.getSiguiente();
				}
			}
			aux = aux.getSiguiente();
		}
	}

	/**
	 * Inserta el elemento que se le pasa por parametro en forma ordenada en la
	 * lista comparando su etiqueta con las etiquetas de los demas elementos
	 * 
	 * @return devuelve true si se inserto exitosamente el elemento en la lista.
	 * @param elemento
	 *            a instertar en la lista
	 * 
	 */
	@Override
	public Boolean insertarOrdenado(IElemento elemento) {
		if (esVacia()) {
			setPrimero(elemento);
			return true;
		}
		if (primero.getSiguiente()==null) {
			if (elemento.getEtiqueta().compareTo(primero.getEtiqueta()) > 0) {
				primero.setSiguiente(elemento);
				return true;
			} else {
				elemento.setSiguiente(primero);
				return true;
			}
		}
		IElemento aux = primero;
		while (!aux.equals(null)) {
			/*hay un error aca???*/
			if (aux.getEtiqueta().compareTo(elemento.getEtiqueta()) >= 0) {
				if(aux==primero){
					elemento.setSiguiente(aux);
					setPrimero(elemento);
					return true;
				}
				elemento.setSiguiente(aux);
				return true;
			}
			if (aux.getEtiqueta().compareTo(elemento.getEtiqueta()) < 0) {
				if (aux.getSiguiente()==null) {
					aux.setSiguiente(elemento);
					return true;

				}
				if (aux.getEtiqueta().compareTo(elemento.getEtiqueta()) >= 0) {
					IElemento prev = aux;
					prev.setSiguiente(elemento);
					elemento.setSiguiente(aux.getSiguiente());
					return true;
				} else {
					aux = aux.getSiguiente();
				}
			}
		}
		return null;
	}

	/**
	 * Informa si la lista es vacia o no.
	 * 
	 * @return si la lista es vacia devuelve true, sino devuelve falso.
	 */
	public Boolean esVacia() {
		if (primero!=null) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * Metodo que retorna el largo de la lista
	 * @return
	 */
	public Integer size(){
		if(primero!=null){
			TElemento aux= (TElemento) primero;
			Integer count=-1;
			while(aux!=null){
				count++;
				aux=(TElemento) aux.getSiguiente();
			}
			return count;
		}
		return null;
	}

}
